//
//  PureVirtual_abstractBaseClass.hpp
//  learnC++
//
//  Created by liuzhibing on 2018/6/15.
//  Copyright © 2018年 yunfan.com. All rights reserved.
//

#ifndef PureVirtual_abstractBaseClass_hpp
#define PureVirtual_abstractBaseClass_hpp

#include <stdio.h>
#include <iostream>
#include <string>

//1、要创建一个纯虚函数，而不是为该函数定义一个主体，我们只需将该函数赋值为0即可。
//2、当我们为我们的类添加一个纯虚函数时，我们实际上是在说，“由派生类来实现这个函数”。
//3、使用纯虚函数有两个主要后果：首先，任何具有一个或多个纯虚函数的类都将成为抽象基类，这意味着它不能被实例化！
//4、任何派生类都必须为此函数定义一个主体，或者派生类也将被视为抽象基类(抽象类不能初始化)。
//5、抽象类仍然有虚拟表，因为如果您有抽象类的指针或引用，仍然可以使用这些表。如果没有提供覆盖，纯虚拟函数的虚拟表项通常包含空指针，或者指向打印错误的泛型函数（有时该函数被命名为__purecall）。
//6、不要忘记为你的接口类包含一个虚拟析构函数，以便在删除指向接口的指针时调用适当的派生析构函数。

class Animal2 {
    std::string m_name;
    
public:
    
    Animal2(std::string name):m_name(name){
        
    }
    
    std::string getName(){return m_name;}
    
    virtual const char* speak() = 0;//现在这是一个纯虚函数，还有这个类是抽象类了，无法实例化
    //纯虚函数也可以有默认实现，如果派生类觉得满意可以直接调用基类的默认实现（但必须要实现纯虚函数）详见cpp
    
    virtual ~Animal2(){
        
    }
};

class Cat2 : public Animal2 {
    
    
public:
    Cat2(std::string name):Animal2(name){
        
    }
    
    virtual const char* speak(){return "Meow";}
    
    virtual ~Cat2(){}
};

class Dog2 : public Animal2 {
    
    
public:
    
    Dog2(std::string name):Animal2(name){
        
    }
    
    virtual const char* speak(){return "Woof";}
    virtual ~Dog2(){}
};

class Cow : public Animal2 {
    
public:
    Cow(std::string name):Animal2(name){
        
    }
    
    //满意基类的speak函数，可以直接调用
    virtual const char* speak(){
        return Animal2::speak();
    }
    virtual ~Cow(){}
};


/*
 //
 class Base
 {
 public:
 const char* sayHi() { return "Hi"; } // a normal non-virtual function
 
 virtual const char* getName() { return "Base"; } // a normal virtual function
 
 virtual int getValue() = 0; // a pure virtual function
 
 int doSomething() = 0; // Compile error: can not set non-virtual functions to 0
 };
 */


#endif /* PureVirtual_abstractBaseClass_hpp */
